const express = require('express')
const session = require('express-session')
const MongoStore = require('connect-mongo')(session)
const FileStreamRotator = require('file-stream-rotator') // 日志分割
const compression = require('compression') // 用户开启Gzip
const flash = require('connect-flash') // 用于session提醒
const engine = require('ejs-mate')
const fs = require('fs')
const path = require('path')
const favicon = require('serve-favicon')
const logger = require('morgan')
const cookieParser = require('cookie-parser')
const bodyParser = require('body-parser')
require('body-parser-xml')(bodyParser)
const expressValidator = require('express-validator')
const sassMiddleware = require('node-sass-middleware')
const device = require('express-device')
const moment = require('moment')
const validatorMethods = require('./utils/validatorMethods')
const index = require('./routes/index')
// var wx = require('./routes/wx')
// var mobile = require('./routes/mobile');
const tool = require('./routes/tool')
const admin = require('./admin/app')
const pathBlack = require('./utils/pathBlack')
const config = require('./config')

const app = express()
app.set('env', 'production')
app.engine('ejs', engine)
// view engine setup
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'ejs')
app.disable('x-powered-by')
// uncomment after placing your favicon in /public
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')))
let errorLogfile
const logDirectory = path.join(__dirname, 'log')
fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory)
if (app.get('env') !== 'production') {
  app.use(sassMiddleware({
    src: path.join(__dirname, 'public/css'),
    dest: path.join(__dirname, 'public/css'),
    // includePaths:[path.join(__dirname,"/node_modules/bootstrap-sass/assets/stylesheets/")],
    // includePaths:[path.join(__dirname,"node_modules/foundation-sites/assets/")],
    indentedSyntax: false, // true = .sass and false = .scss
    sourceMap: false,
    // outputStyle: 'compressed',
    debug: true,
    outputStyle: 'extended',
    prefix: '/css',
  }))
}

app.use(compression()) // gzip压缩
app.use(express.static(path.join(__dirname, 'public')))
// app.use(express.static(path.join(__dirname, 'admin/public')));
console.log(app.get('env'))
if (app.get('env') === 'development') {
  app.use(logger('dev', { stream: process.stdout }))
} else {
  errorLogfile = fs.createWriteStream(path.join(logDirectory, 'error.log'), { flags: 'a' })
  const accessLogStream = FileStreamRotator.getStream({
    date_format: 'YYYYMMDD',
    filename: path.join(logDirectory, 'access-%DATE%.log'),
    frequency: 'daily',
    verbose: false,
  })
  logger.token('real-ip', (req, res) => req.get('X-Real-IP') || req.get('X-Forwarded-For') || req.ip)
  logger.token('user-id', (req, res) => {
    if (req.session && req.session.user) {
      return `[${req.session.user.nickname || ''},${req.session.user.email || ''}]`
    }
    return '[no_login]'
  })
  logger.token('type', (req, res) => req.headers['content-type'])
  logger.token('date-moment', (req, res) => moment(new Date()).format('YYYY-MM-DD HH:mm:ss'))
  app.use(logger(':date-moment :real-ip :user-id :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms :referrer :user-agent', { stream: process.stdout }))
  app.use(logger(':date-moment :real-ip :user-id :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms :referrer :user-agent', { stream: accessLogStream }))
}
app.use(pathBlack)
app.use(bodyParser.xml({
  limit: '100kb', // Reject payload bigger than 1 MB
  defaultCharset: 'utf-8',
  xmlParseOptions: {
    normalize: true, // Trim whitespace inside text nodes
    normalizeTags: true, // Transform tags to lowercase
    explicitArray: false, // Only put nodes in array if >1
  },
  verify(req, res, buf, encoding) {
    console.log(buf, '------')
    if (buf && buf.length) {
      // Store the raw XML
      req.rawBody = buf.toString(encoding || 'utf8')
    }
  },
}))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ limit: '3mb', extended: false }))
app.use(device.capture())
device.enableDeviceHelpers(app)
app.use(expressValidator(validatorMethods))
app.use(cookieParser())
app.use(session({
  resave: false, // 新增
  saveUninitialized: true, // 新增
  secret: 'czwaiwai.bssfood.com',
  store: new MongoStore({ url: config.db }),
}))
app.use(flash())
app.use((req, res, next) => {
  res.locals = Object.assign(res.locals, {
    title: '白石山农场',
    basePath: req.path,
    error: req.flash('error').toString(),
    success: req.flash('success').toString(),
    user: req.session.user,
  })
  res.locals.query = req.query
  next()
})

app.use('/', index)
// app.use('/wx', wx);
// app.use('/app', mobile);
app.use('/tool', tool)
app.use('/admin', admin)

// catch 404 and forward to error handler
app.use((req, res, next) => {
  const err = new Error('您要的页面没有找到')
  err.status = 404
  // next(err);
  res.render('error404', { title: '页面未找到' })
})
// error handler
app.use((err, req, res, next) => {
  // set locals, only providing error in development
  res.locals.message = err.message
  res.locals.error = req.app.get('env') === 'development' ? err : {}
  if (errorLogfile) {
    errorLogfile.write(`[${new Date()}] ${req.url}\n${err.stack}`)
  }
  if (req.xhr) {
    res.status(500).json({ code: -1, message: err.message, stack: err.stack })
  } else {
    // render the error page
    res.status(err.status || 500)
    res.render('error', { title: '网站错误' })
  }
})

module.exports = app
